#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>

#define High 15
#define Width 35

//函数外全局变量定义
int food_x; food_y;				//记录食物位置
int moveDirection;				//小蛇移动方向 1，2，3，4，分别表示上下左右
int canvas[High][Width] = {0};	//二维数组储存游戏画布中对应的元素
								//0为空格，-1为边框#；1为蛇头@，>1为蛇身，-2为食物

void gotoxy(int x, int y)
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(handle, pos);
}

void HideCursor()
{
	CONSOLE_CURSOR_INFO cursor_info = { 1,0 };//第二个值为0表示隐藏光标
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

void startup()						//数据初始化
{
	int i, j;


	//以下设定边框
	for (i = 0; i < High; i++)
	{
		canvas[i][0] = -1;
		canvas[i][Width - 1] = -1;
	}
	for (j = 0; j < Width; j++)
	{
		canvas[0][j] = -1;
		canvas[High - 1][j] = -1;
	}

	//以下初始化蛇身
	canvas[High / 2][Width / 2] = 1;

	for (i = 1; i <= 4; i++)
		canvas[High / 2][Width / 2 - i] = i + 1;

	moveDirection = 4;

	//初始化食物的位置
	food_x = rand() % (High - 5) + 2;
	food_y = rand() % (Width - 5) + 2;
	canvas[food_x][food_y] = -2;

	HideCursor(); //隐藏光标
}

void moveSnakeByDirection()
{
	int i, j;
	int max = 0;
	int OldTail_i, OldTail_j;			//记录旧蛇尾
	int OldHead_i, OldHead_j;			//记录旧蛇头

	for(i=1;i<High-1;i++)
		for (j = 1; j < Width - 1; j++)
		{
			if (canvas[i][j] > 0)
			{
				//对大于0的数+1
				canvas[i][j]++;

				if (max < canvas[i][j])
				{
					max = canvas[i][j];
					OldTail_i = i;
					OldTail_j = j;
				}

				if (canvas[i][j] == 2)
				{
					OldHead_i = i;
					OldHead_j = j;
				}
			}
		}

	int newHead_i, newHead_j;

	if (moveDirection == 1)				//向上
	{
		newHead_i = OldHead_i - 1;
		newHead_j = OldHead_j;
	}
	if (moveDirection == 2)				//向下
	{
		newHead_i = OldHead_i + 1;
		newHead_j = OldHead_j;
	}
	if (moveDirection == 3)				//向左
	{
		newHead_i = OldHead_i;
		newHead_j = OldHead_j - 1;
	}
	if (moveDirection == 4)				//向右
	{
		newHead_i = OldHead_i;
		newHead_j = OldHead_j + 1;
	}

	//判断小蛇蛇头是否碰到食物
	if (canvas[newHead_i][newHead_j] == -2)
	{
		//食物重新生成
		canvas[food_x][food_y] = 0;
		food_x = rand() % (High - 5) + 2;
		food_y = rand() % (Width - 5) + 2;
		canvas[food_x][food_y] = -2;

		//吃到食物长度加1
	}
	else
	{
		//没有迟到食物长度不变
		canvas[OldTail_i][OldTail_j] = 0;	//最大值所在元素变为0
	}

	//判断小蛇蛇头撞到边框或自身，游戏失败
	if (canvas[newHead_i][newHead_j] > 0 || canvas[newHead_i][newHead_j] == -1)
	{
		printf("游戏失败\n");
		exit(0);
	}
	else
	{
		canvas[newHead_i][newHead_j] = 1;
	}
}

void show()    //显示画面
{
	gotoxy(0, 0);					//光标移动到原点
	int i, j;
	for (i = 0; i < High; i++)
	{
		for (j = 0; j < Width; j++)
		{
			if (canvas[i][j] == 1)
				printf("@");		//输出蛇头
			if (canvas[i][j] > 1)
				printf("*");		//输出蛇身
			if (canvas[i][j] == -1)
				printf("#");		//输出边框
			if (canvas[i][j] == -2)
				printf("F");		//输出食物
			else if (canvas[i][j] == 0)
				printf(" ");		//输出空格
		}
		printf("\n");
	}
}

void updateWithoutInput()		//与用户输入无关的更新
{
	moveSnakeByDirection();
	Sleep(150);
}
void updateWithInput()			//与用户输入有关的更新
{
	char input;
	if (kbhit())	//判断是否有输入
	{
		input = getch();

		if (input == 'a')
			moveDirection = 3;
		if (input == 'd')
			moveDirection = 4;
		if (input == 'w')
			moveDirection = 1;
		if (input == 's')
			moveDirection = 2;
	}
}

int main()
{
	startup();
	while (1)
	{
		show();					//显示画面
		updateWithoutInput();	//与用户输入无关的更新
		updateWithInput();		//与用户输入有关的更新
	}
	return 0;
}